home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
debugnub
/
RDTMain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-16
|
31KB
|
1,341 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* RDTMain.c
*
* Demers, April 25, 1990 4:22:10 pm PDT
* Udagawa, September 20, 1989 3:40:21 pm PDT
* CHauser, September 19, 1989 4:54:44 pm PDT
*
*/
#include "xr/BasicTypes.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/Errno.h"
#include "xr/CirioNubTypes.h"
#include "xr/RDTProcs.h"
#include <sgtty.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <fcntl.h>
#include <ctype.h>
/*
* misc parameters
*/
/*
* global state
*/
static char *RDT_debuggeeName = NIL;
static unsigned RDT_debuggeePort = 0;
static unsigned RDT_debuggeeProtocolVersion = 0;
static bool RDT_connected = FALSE;
static int RDT_examinee = -1;
static void
RDT_SetDebuggeeName(name)
char *name;
{
if( RDT_debuggeeName != NIL ) {
(void) free(RDT_debuggeeName);
RDT_debuggeeName = NIL;
}
if( name != NIL ) {
RDT_debuggeeName = (char *) malloc(1+strlen(name));
(void) strcpy(RDT_debuggeeName, name);
}
}
/*
* UNIX signal handlers ...
*/
static int RDT_numSIGINTs = 0;
static int
RDT_OnSIGINT ()
{
RDT_numSIGINTs += 1;
return 0;
}
static int
RDT_OnSIGALRM ()
{
return 0;
}
static void
RDT_InstallHandler (signal, handler)
int signal;
void (*handler)();
{
struct sigvec vec;
vec.sv_mask = 0;
vec.sv_flags = SV_INTERRUPT; /* force read to be interrupted */
vec.sv_handler = handler;
(void) sigvec(signal, &vec, NIL);
}
/*
* Command parsing stuff
*/
#define RDT_INCODE_ERR (-1)
#define RDT_INCODE_INT (-2)
#define RDT_STDIN 0
#define RDT_STDOUT 1
#define CMD_BUF_LEN 256
#define RDT_MAX_ARGS 20
static char RDT_cmdBuf[CMD_BUF_LEN];
static char *RDT_cmdPtr = &(RDT_cmdBuf[0]);
#define RDT_cmdLim (&(RDT_cmdBuf[CMD_BUF_LEN-1]))
static char *RDT_cmd = NIL;
static int RDT_argc = 0;
static char *(RDT_argv[RDT_MAX_ARGS]);
static void
RDT_DiscardInput ()
{
int which = FREAD;
(void)ioctl(RDT_STDIN, TIOCFLUSH, &which);
RDT_cmdBuf[0] = 0;
RDT_cmdPtr = RDT_cmdBuf;
}
static int
RDT_GetChar ()
/*
Return next input char or DBT_INCODE code.
*/
{
char buf[1];
int numSIGINTs = RDT_numSIGINTs;
if( read(RDT_STDIN, buf, 1) != 1 )
return( (errno == EINTR) ? RDT_INCODE_INT : RDT_INCODE_ERR );
if( numSIGINTs < RDT_numSIGINTs ) return(RDT_INCODE_INT);
return( buf[0] );
}
static int
RDT_GetLine ()
/*
Read next input line; return its length or RDT_INCODE code.
*/
{
int c;
char *p;
RDT_cmdPtr = p = RDT_cmdBuf;
for(;;) {
if( (c = RDT_GetChar()) < 0 ) break;
if( p < RDT_cmdLim ) *p++ = c;
if( c == '\n' ) {
*p = 0;
return( p - RDT_cmdBuf );
}
}
return( (c == RDT_INCODE_INT) ? RDT_INCODE_INT : RDT_INCODE_ERR );
}
static bool
RDT_IsWhite(c)
char c;
/*
Return TRUE iff next char is white space.
*/
{
switch(c) {
case ' ':
case '\n':
case '\r':
case '\t':
case 0:
return(TRUE);
default:
return(FALSE);
}
}
static char *
RDT_GetToken ()
/*
Isolate next token, return pointer to it or NIL.
*/
{
char *p;
char *result;
char c;
p = RDT_cmdPtr;
for(;;) {
c = *p;
if( (c == 0) || (c == '\n') ) return( NIL );
if( !RDT_IsWhite(c) ) break;
p++;
}
result = p;
for(;;) {
c = *p;
if( c == 0 ) break;
if( RDT_IsWhite(c) || (c == '\n') ) { *p++ = 0; break; }
p++;
}
RDT_cmdPtr = p;
return( result );
}
static int
RDT_WaitForCmd ()
{
int ans;
RDT_cmd = NIL;
RDT_argc = 0;
RDT_Msg("(rdt): ");
RDT_DiscardInput();
ans = RDT_GetLine();
switch( ans ) {
case RDT_INCODE_INT:
case RDT_INCODE_ERR:
return ans;
default:
;
}
if( (RDT_cmd = RDT_GetToken()) == NIL ) return 0;
for(;;) {
char *token;
if( (token = RDT_GetToken()) == NIL ) return 0;
if( RDT_argc < RDT_MAX_ARGS ) {
RDT_argv[RDT_argc] = token;
RDT_argc += 1;
}
}
/*NOTREACHED*/
}
typedef
# define MATCH_NONE 0
# define MATCH_HELP 1
# define MATCH_INVOKE 2
int RDT_CmdMatchResult;
static bool
RDT_MatchInner(input, fullName, len)
char *input;
char *fullName;
int len;
{
int i;
for( i = 0; ; i++ ) {
char c = input[i];
if( c == 0 ) return( i >= len );
if( c != fullName[i] ) return( FALSE );
}
}
static RDT_CmdMatchResult
RDT_CmdMatch(fullName, len)
char *fullName;
int len;
{
if( RDT_MatchInner(RDT_cmd, fullName, len) ) return( MATCH_INVOKE );
if( RDT_MatchInner(RDT_cmd, "?", 1 )
|| RDT_MatchInner(RDT_cmd, "help", 4 ) ) {
if( RDT_argc < 1 ) return( MATCH_HELP );
if( RDT_MatchInner(RDT_argv[0], fullName, len) ) return( MATCH_HELP );
return( MATCH_NONE );
}
return( MATCH_NONE );
}
static bool
RDT_Confirm(msg)
char *msg;
{
bool ans;
int c;
for(;;) {
RDT_Msg("%s (y|n): ", msg);
RDT_DiscardInput();
switch(c = RDT_GetChar()) {
case 'y':
case 'Y':
ans = TRUE;
goto out;
case 'n':
case 'N':
ans = FALSE;
goto out;
case RDT_INCODE_ERR:
ans = TRUE; /* sigh */
goto out;
case RDT_INCODE_INT:
default:
;
}
}
out:
while( ((c = RDT_GetChar()) >= 0) && (c != '\n') ) ;
return( ans );
}
/*
* Command primitives ...
*/
static int
RDT_DoKillWorld ()
{
int i, ans;
if( !RDT_Confirm("Kill world? ") ) return 1;
RDT_Msg("Good-bye.\n");
ans = RDT_KillWorld();
RDT_connected = FALSE;
return ans;
}
static int
RDT_DoSetDBStat (stat)
int stat;
{
int ans;
ans = RDT_SetDBStat( stat, 6000 );
if( ans > 0 ) {
RDT_Msg("Can't set debuggee state to %d\n", stat);
ans = 0;
}
return ans;
}
static int
RDT_DoStop ()
{
int ans;
if( (ans = RDT_DoSetDBStat(XR_DBSTAT_STOP)) < 0 ) {
RDT_Msg("Can't stop debuggee.\n");
}
return ans;
}
static int
RDT_GetTIDArg (i, dataPtr)
unsigned i;
CirioNubThreadData *dataPtr;
{
int index, ans;
if( i >= RDT_argc ) {
RDT_Msg("ThreadID?\n");
return( 1 );
}
index = atoi(RDT_argv[i]);
ans = RDT_GetThread(index, dataPtr);
if( ans < 0 ) {
RDT_Msg("Can't lookup thread %s.\n", RDT_argv[i]);
} else if( ans > 0 ) {
RDT_Msg("Thread %s nonexistent.\n", RDT_argv[i]);
} else if( !RDT_ThreadIsActive(*dataPtr) ) {
RDT_Msg("Thread %d inactive.\n", (*dataPtr)->cntd_index);
RDT_FreeThreadData(dataPtr);
ans = 1;
}
return ans;
}
static int
RDT_DoGetState()
{
int index = 999999;
int dbStat = 999999;
int ans;
ans = RDT_GetDBStat( /*timeout*/ 0, &index, &dbStat );
if( ans >= 0 ) {
if( index >= 0 ) {
RDT_Msg("Examining %d.\n", index);
} else switch(dbStat) {
case XR_DBSTAT_STOP:
RDT_Msg("Stopped.\n");
break;
case XR_DBSTAT_RUN0:
RDT_Msg("Running uniprocessor.\n");
break;
case XR_DBSTAT_RUN:
RDT_Msg("Running multiprocessor.\n");
break;
default:
RDT_Msg("Trying to examine %d.\n", dbStat);
break;
}
ans = 0;
}
return ans;
}
static int
RDT_DoExamine ()
{
CirioNubThreadData threadData = NIL;
int ans;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
RDT_Msg("Examine %d ... ", threadData->cntd_index);
if( (ans = RDT_DoSetDBStat(threadData->cntd_index)) >= 0 ) {
RDT_Msg("ok\n");
} else {
(void) RDT_DoStop();
}
RDT_examinee = threadData->cntd_index;
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_DoFreeze ()
{
CirioNubThreadData threadData = NIL;
int ans;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
if( threadData->cntd_dbFrozen ) {
RDT_Msg("Thread %d already frozen.\n", threadData->cntd_index);
goto Out;
}
RDT_Msg("Freezing %d ... ", threadData->cntd_index);
ans = RDT_IssueThreadCommand (
threadData->cntd_index,
TRUE, TRUE,
FALSE, 0 );
RDT_Msg("%s.\n", ((ans == 0) ? "frozen" : "failed") );
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_DoAbort ()
{
CirioNubThreadData threadData = NIL;
int ans;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
if( threadData->cntd_dbMsg <= 0 ) {
RDT_Msg("Thread %d not calling debugger.\n",
threadData->cntd_index);
goto Out;
}
RDT_Msg("Aborting %d ... ", threadData->cntd_index);
ans = RDT_IssueThreadCommand (
threadData->cntd_index,
TRUE, FALSE,
TRUE, XR_DB_MSG_ABORT_REPLY );
RDT_Msg("%s.\n", ((ans == 0) ? "aborted" : "failed") );
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_DoThaw ()
{
CirioNubThreadData threadData = NIL;
int ans;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
RDT_Msg("Thawing %d ... ", threadData->cntd_index);
ans = RDT_IssueThreadCommand (
threadData->cntd_index,
TRUE, FALSE, /* clear dbFreeze */
XR_DB_MSG_IS_REQUEST(threadData->cntd_dbMsg),
XR_DB_MSG_PROCEED_REPLY /* proceed if calling debugger */
);
RDT_Msg("%s.\n", ((ans == 0) ? "thawed" : "failed") );
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_DoKill ()
{
CirioNubThreadData threadData = NIL;
int ans;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
if( !(XR_DB_MSG_IS_REQUEST(threadData->cntd_dbMsg)) ) {
RDT_Msg("Thread %d not calling debugger.\n",
threadData->cntd_index);
goto Out;
}
RDT_Msg("Killing %d ... ", threadData->cntd_index);
ans = RDT_IssueThreadCommand (
threadData->cntd_index,
TRUE, TRUE,
TRUE, XR_DB_MSG_EXIT_REPLY );
RDT_Msg("%s.\n", ((ans == 0) ? "r.i.p" : "won't die") );
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static bool
RDT_ThreadIsActive(cntd)
CirioNubThreadData cntd;
{
if( cntd == NIL ) {
return FALSE;
} else switch( cntd->cntd_sStat ) {
case XR_SSTAT_NONE:
case XR_SSTAT_FREE:
return FALSE;
case XR_SSTAT_READY:
case XR_SSTAT_RUN:
case XR_SSTAT_WAIT_ML:
case XR_SSTAT_WAIT_CV:
return TRUE;
default:
RDT_Msg( "(RDT_ThreadIsActive internal error %d)\n",
cntd->cntd_sStat );
return FALSE;
}
}
static void
RDT_PutOneThread (cntd)
CirioNubThreadData cntd;
{
static char sstat_chars[] = "?FRRMCH";
if( cntd->cntd_dbMsg != 0 ) RDT_Msg("*[%d]", cntd->cntd_dbMsg);
RDT_Msg("%d%c", cntd->cntd_index, sstat_chars[cntd->cntd_sStat]);
RDT_Msg( "%s%s ",
((cntd->cntd_index == RDT_examinee) ? "e" : ""),
(cntd->cntd_dbFrozen ? "f" : "") );
}
static int
RDT_DoPutThreads()
{
int i, ans;
CirioNubThreadData threadData = NIL;
for( i = 0; ; i++ ) {
ans = RDT_GetThread(i, &threadData);
if( ans != 0 ) break;
if( RDT_ThreadIsActive(threadData) ) RDT_PutOneThread(threadData);
RDT_FreeThreadData(&threadData);
}
RDT_Msg("\n");
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
#if defined(sparc)
static int
RDT_DoGetAndDisplayPrevFrame(spp, fpp, pcp, prolixity)
XR_Pointer *spp, *fpp, *pcp;
int prolixity;
{
int ans;
XR_Pointer savedRegs[16];
ans = RDT_GetWords32( ((unsigned )(*spp)),
(sizeof savedRegs), ((unsigned *)(savedRegs)) );
if( ans != (sizeof savedRegs) ) return (-1);
if( prolixity > 1 ) {
XR_Pointer *inReg = &savedRegs[8];
int i = 0;
int j;
while( i < 8 ) {
for( j = 0; j < 4; j++ ) {
RDT_Msg(" i%-2d: %8x", i, *inReg);
i += 1;
inReg += 1;
}
RDT_Msg("\n");
}
}
*pcp = XR_OLD_PC_FROM_FRAME(0, (&(savedRegs[0])) );
*spp = XR_OLD_SP_FROM_FRAME(0, (&(savedRegs[0])) );
*fpp = /* XR_OLD_FP_FROM_FRAME(0, (&(savedRegs[0])) ); ??? */ 0;
return 0;
}
#else
static int
RDT_DoGetPrevFrameAndPC(spp, fpp, pcp)
XR_Pointer *spp, *fpp, *pcp;
{
--> fix me for target architecture <--
}
#endif
static int
RDT_DoDisplayProcName(pc, sp, prolixity)
XR_Pointer pc;
XR_Pointer sp;
int prolixity;
{
int ans;
CirioNubPCInfo procInfo = NIL;
ans = RDT_PCtoInfo(pc, &procInfo);
if( ans == 0 ) {
RDT_Msg( "%s ", ((procInfo->procName != NIL)
? procInfo->procName : "(no name)" ) );
RDT_Msg( "(pc 0x%x, ", pc);
RDT_Msg( "sp 0x%x) ", sp);
if( prolixity > 0 ) {
if( procInfo->guessedEmbeddedFileName != NIL ) {
RDT_Msg("from embedded file %s ",
procInfo->guessedEmbeddedFileName );
}
RDT_Msg( "in file %s.\n", ((procInfo->fileName != NIL)
? procInfo->fileName : "(unknown)" ) );
} else {
RDT_Msg( "\n");
}
} else {
RDT_Msg("(can't find pc 0x%x).\n", pc);
}
if( procInfo != NIL ) RDT_FreePCInfo (&procInfo);
return ans;
}
static int
RDT_DoDisplayOneThread(cntd, nf, prolixity)
CirioNubThreadData cntd;
int nf;
int prolixity;
{
int ans = 0;
XR_Pointer pc, fp, sp;
int i;
RDT_PutOneThread(cntd);
RDT_Msg(" pri = %d", cntd -> cntd_pri);
RDT_Msg(" stack display:\n");
pc = cntd->cntd_pc;
fp = cntd->cntd_fp;
sp = cntd->cntd_sp;
for(i = 0; ; i++) {
if( i == nf ) break;
if( pc == NIL ) break;
RDT_Msg("%d.%d: ", cntd->cntd_index, i);
(void) RDT_DoDisplayProcName(pc, sp, prolixity);
if( sp == NIL ) break;
ans = RDT_DoGetAndDisplayPrevFrame(&sp, &fp, &pc, prolixity);
if( ans != 0 ) break;
}
return ans;
}
static int
RDT_DoDisplayThreads()
{
CirioNubThreadData threadData = NIL;
int i, ans;
int numFrames = -1;
int prolixity = 0;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
if( RDT_argc > 0 ) {
if( RDT_argc > 1 ) {
numFrames = atoi(RDT_argv[1]);
if( RDT_argc > 2 ) {
prolixity = atoi(RDT_argv[2]);
}
}
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
if( RDT_ThreadIsActive(threadData) ) {
(void)RDT_DoDisplayOneThread(threadData, numFrames, prolixity);
} else {
RDT_Msg("Thread %d inactive.\n", threadData->cntd_index);
}
}
} else {
for(i = 0; ; i++ ) {
ans = RDT_GetThread(i, &threadData);
if( ans != 0 ) break;
if( RDT_ThreadIsActive(threadData) ) {
ans = RDT_DoDisplayOneThread(threadData, numFrames, prolixity);
if( ans != 0 ) break;
}
RDT_FreeThreadData(&threadData);
}
}
Out:
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_PutStr(str, fd)
char *str;
int fd;
{
int ans, len;
len = strlen(str);
while( len > 0 ) {
ans = write(fd, str, len);
if( ans <= 0 ) return ans;
str += ans;
len -= ans;
}
return 0;
}
static int
RDT_DoSaveProcName(pc, fd)
XR_Pointer pc;
int fd;
{
int ans;
CirioNubPCInfo procInfo = NIL;
ans = RDT_PCtoInfo(pc, &procInfo);
if( ans == 0 ) {
if( procInfo->guessedEmbeddedFileName != NIL )
ans = RDT_PutStr( procInfo->guessedEmbeddedFileName, fd );
if( ans == 0 )
ans = RDT_PutStr( " ", fd );
}
if( procInfo != NIL ) RDT_FreePCInfo (&procInfo);
return ans;
}
static int
RDT_DoSaveOneThread(cntd, nf, fd)
CirioNubThreadData cntd;
int nf;
int fd;
{
int ans = 0;
XR_Pointer pc, fp, sp;
int i;
pc = cntd->cntd_pc;
fp = cntd->cntd_fp;
sp = cntd->cntd_sp;
for(i = 0; ; i++) {
if( i == nf ) break;
if( pc == NIL ) break;
ans = RDT_DoSaveProcName(pc, fd);
if( ans != 0 ) break;
if( sp == NIL ) break;
ans =RDT_DoGetAndDisplayPrevFrame(&sp, &fp, &pc, /*prolixity=*/ 0);
if( ans != 0 ) break;
}
return ans;
}
char *RDT_saveFileName = "DBXObjectNames";
static int
RDT_DoSave()
{
CirioNubThreadData threadData = NIL;
int i, ans;
int numFrames = -1;
int fd = -1;
if( (ans = RDT_DoStop()) < 0 ) goto Out;
fd = open(RDT_saveFileName, (O_WRONLY|O_CREAT|O_TRUNC), 0666);
if( fd < 0 ) {
RDT_Msg("Cannot create %s.\n", RDT_saveFileName);
ans = 1;
goto Out;
}
ans = RDT_PutStr("modules select ", fd);
if( ans != 0 ) {
ans = 1;
goto Out;
}
if( RDT_argc > 0 ) {
if( RDT_argc > 1 ) {
numFrames = atoi(RDT_argv[1]);
}
if( (ans = RDT_GetTIDArg(0, &threadData)) == 0 ) {
if( RDT_ThreadIsActive(threadData) ) {
(void)RDT_DoSaveOneThread(threadData, numFrames, fd);
} else {
RDT_Msg("Thread %d inactive.\n", threadData->cntd_index);
}
}
} else {
for(i = 0; ; i++ ) {
ans = RDT_GetThread(i, &threadData);
if( ans != 0 ) break;
if( RDT_ThreadIsActive(threadData) ) {
ans = RDT_DoSaveOneThread(threadData, numFrames, fd);
}
RDT_FreeThreadData(&threadData);
if( ans != 0 ) break;
}
}
(void) RDT_PutStr("\n", fd);
Out:
if( fd >= 0 ) (void)close(fd);
if( threadData != NIL ) RDT_FreeThreadData(&threadData);
return ans;
}
static int
RDT_DoGetDebuggeeProtocolVersion(desiredVersion)
unsigned desiredVersion;
{
unsigned hisVersion;
int ans;
ans = RDT_Null(desiredVersion, &hisVersion);
if( ans == 0 ) {
if( hisVersion != desiredVersion ) {
RDT_Msg("Protocol version mismatch. Wanted %d. ", desiredVersion);
ans = -1;
}
RDT_Msg("Debuggee protocol version %d.\n", hisVersion);
}
return ans;
}
static int
RDT_DoWPeek()
{
unsigned addr;
int i;
int n = 1;
unsigned buf[64];
if( RDT_argc < 1 ) return(-1);
i = strtol(RDT_argv[0], 0, 0);
if( i == (-1) ) {
RDT_Msg("Bad address %s\n", RDT_argv[0]);
return (-1);
}
addr = ((unsigned)(i & (~(sizeof(unsigned)-1))));
if( RDT_argc >= 2 ) {
n = atoi(RDT_argv[1]);
if( (n <= 0) || (n > ((sizeof buf)/sizeof(unsigned))) ) {
RDT_Msg("Bad count %s\n", RDT_argv[1]);
return (-1);
}
}
i = RDT_GetWords32(addr, n*sizeof(unsigned), buf);
if( i != (n*sizeof(unsigned)) ) {
RDT_Msg("can't read debuggee memory, err %d\n", i);
return (-1);
}
for( i = 0; i < n; i++ ) {
RDT_Msg(" 0x%x: 0x%x (%d)\n", addr, buf[i], buf[i]);
addr += sizeof(unsigned);
}
}
static int
RDT_DoBPeek()
{
unsigned addr;
int i;
int n = 1;
char buf[64];
if( RDT_argc < 1 ) return(-1);
i = strtol(RDT_argv[0], 0, 0);
if( i == (-1) ) {
RDT_Msg("Bad address %s\n", RDT_argv[0]);
return (-1);
}
addr = ((unsigned)(i));
if( RDT_argc >= 2 ) {
n = atoi(RDT_argv[1]);
if( (n <= 0) || (n > ((sizeof buf)/sizeof(char))) ) {
RDT_Msg("Bad count %s\n", RDT_argv[1]);
return (-1);
}
}
i = RDT_GetBytes(addr, n*sizeof(char), buf);
if( i != (n*sizeof(char)) ) {
RDT_Msg("can't read debuggee memory, err %d\n", i);
return (-1);
}
for( i = 0; i < n; i++ ) {
int c = toascii(buf[i]);
if( !(isgraph(c)) ) c = '?';
RDT_Msg(" 0x%x: 0x%x ('%c')\n", addr, buf[i], c);
addr += sizeof(char);
}
}
static int
RDT_DoWPoke()
{
int i, x;
unsigned addr;
unsigned buf[1];
if( RDT_argc < 1 ) return(-1);
x = strtol(RDT_argv[0], 0, 0);
if( x == (-1) ) {
RDT_Msg("Bad address %s\n", RDT_argv[0]);
return (-1);
}
addr = ((unsigned)(x & (~(sizeof(unsigned)-1))));
for( i = 1; i < RDT_argc; i++ ) {
buf[0] = strtol(RDT_argv[i], 0, 0);
x = RDT_PutWords32(addr, (sizeof buf), buf);
if( x != (sizeof buf) ) {
RDT_Msg("can't write debuggee memory at 0x%x, err %d\n", addr, x);
return (-1);
}
addr += (sizeof buf);
}
}
static int
RDT_DoBPoke()
{
int i, x;
unsigned addr;
char buf[1];
if( RDT_argc < 1 ) return(-1);
x = strtol(RDT_argv[0], 0, 0);
if( x == (-1) ) {
RDT_Msg("Bad address %s\n", RDT_argv[0]);
return (-1);
}
addr = ((unsigned)(x & (~(sizeof(char)-1))));
for( i = 1; i < RDT_argc; i++ ) {
buf[0] = strtol(RDT_argv[i], 0, 0);
x = RDT_PutBytes(addr, (sizeof buf), buf);
if( x != (sizeof buf) ) {
RDT_Msg("can't write debuggee memory at 0x%x, err %d\n", addr, i);
return (-1);
}
addr += (sizeof buf);
}
}
static void
RDT_DoWithConnection( proc, arg )
int (*proc)(/* int arg */);
int arg;
{
int ans;
if( !RDT_connected ) {
RDT_Msg("no connection.\n");
return;
}
ans = (*proc)(arg);
if( ans < 0 ) {
(void)RDT_Disconnect(TRUE);
RDT_connected = FALSE;
RDT_Msg("connection broken.\n");
}
}
static int
RDT_DoConnect()
{
if( RDT_connected ) {
RDT_Msg("Already connected to %s.\n", RDT_debuggeeName);
return 0;
}
if( RDT_argc > 0 ) {
RDT_SetDebuggeeName(RDT_argv[0]);
RDT_debuggeePort = 0;
if( RDT_argc > 1 ) {
int tPort = atoi(RDT_argv[1]);
if( tPort >= 0 ) RDT_debuggeePort = ((unsigned)(tPort));
}
}
if( RDT_debuggeeName == NIL ) {
RDT_Msg("No debuggee specified.\n");
return (0);
}
RDT_Msg("Connecting to %s ", RDT_debuggeeName);
if( RDT_debuggeePort != 0 ) {
RDT_Msg("(port %d) ", RDT_debuggeePort);
}
RDT_Msg("... ");
(void) alarm(10);
if( RDT_Connect(RDT_debuggeeName, RDT_debuggeePort) != cnrc_ok ) {
RDT_Msg("can't connect.\n");
(void) alarm(0);
return (-1);
}
RDT_connected = TRUE;
(void) alarm(0);
return 0;
}
static int
RDT_DoDisconnect(doAbort)
int doAbort;
{
(void) RDT_Disconnect(((bool)(doAbort)));
RDT_connected = FALSE;
return 0;
}
void
RDT_Main (doConnect)
bool doConnect;
{
unsigned emptyCommands = 0;
# define MAX_EMPTY_COMMANDS 50
RDT_InstallHandler(SIGINT, RDT_OnSIGINT);
RDT_InstallHandler(SIGALRM, RDT_OnSIGALRM);
if( doConnect ) {
if( RDT_DoConnect() == 0 ) {
RDT_DoWithConnection( RDT_DoGetDebuggeeProtocolVersion,
RDT_PROCS_VERSION );
}
}
for(;;) {
switch( RDT_WaitForCmd() ) {
case RDT_INCODE_ERR:
if( ++emptyCommands <= MAX_EMPTY_COMMANDS ) continue;
RDT_Msg("RDT_Main emptyCommands error 0\n");
abort();
/*NOTREACHED*/
case RDT_INCODE_INT:
RDT_Msg(" ... (interrupted).\n");
continue;
case 0:
break;
default:
RDT_Msg("RDT_Main botch 0\n");
abort();
/*NOTREACHED*/
}
if( RDT_cmd == NIL ) {
if( ++emptyCommands <= MAX_EMPTY_COMMANDS ) continue;
RDT_Msg("RDT_Main emptyCommands error 1\n");
abort();
/*NOTREACHED*/
}
emptyCommands = 0;
switch( RDT_CmdMatch("stop", 3) ) {
case MATCH_HELP:
RDT_Msg("sto(p -- stop all processors\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoStop, 0 );
RDT_Msg("STOP: ");
RDT_DoWithConnection( RDT_DoPutThreads, 0 );
continue;
}
switch( RDT_CmdMatch("state", 3) ) {
case MATCH_HELP:
RDT_Msg("sta(te -- print state\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoGetState, 0 );
continue;
}
switch( RDT_CmdMatch("uniprocessor", 3) ) {
case MATCH_HELP:
RDT_Msg("uni(processor -- run with 1 processor\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoSetDBStat, XR_DBSTAT_RUN0 );
RDT_examinee = -1;
continue;
}
switch( RDT_CmdMatch("multiprocessor", 5) ) {
case MATCH_HELP:
RDT_Msg("multi(processor -- run with all processors\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoSetDBStat, XR_DBSTAT_RUN );
RDT_examinee = -1;
continue;
}
switch( RDT_CmdMatch("examine" /*tid*/, 1) ) {
case MATCH_HELP:
RDT_Msg( "%s -- %s\n",
"e(xamine threadid", "examine a thread" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoExamine, 0 );
continue;
}
switch( RDT_CmdMatch("freeze" /*pid*/, 1) ) {
case MATCH_HELP:
RDT_Msg("f(reeze threadid -- freeze a thread\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoFreeze, 0 );
continue;
}
switch( RDT_CmdMatch("kill" /*pid*/, 1) ) {
case MATCH_HELP:
RDT_Msg("k(ill threadid -- kill thread calling debugger\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoKill, 0 );
continue;
}
switch( RDT_CmdMatch("abort", 1) ) {
case MATCH_HELP:
RDT_Msg("a(bort [(current thread)|*|pid ...] -- abort thread\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoAbort, 0 );
continue;
}
switch( RDT_CmdMatch("thaw", 1) ) {
case MATCH_HELP:
RDT_Msg("t(haw [(current thread)|*|pid ...] -- thaw thread\n");
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoThaw, 0 );
continue;
}
switch( RDT_CmdMatch("display", 1) ) {
case MATCH_HELP:
RDT_Msg("%s -- %s\n",
"d(isplay [threadid [nFrames [verboseLevel]]]",
"display thread stack" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoDisplayThreads, 0 );
continue;
}
switch( RDT_CmdMatch("peek", 2) ) {
case MATCH_HELP:
RDT_Msg("%s -- %s\n",
"pe(ek address [nWords]",
"display words of memory" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoWPeek, 0 );
continue;
}
switch( RDT_CmdMatch("bpeek", 2) ) {
case MATCH_HELP:
RDT_Msg("%s -- %s\n",
"bp(eek address [nBytes]",
"display bytes of memory" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoBPeek, 0 );
continue;
}
switch( RDT_CmdMatch("poke", 2) ) {
case MATCH_HELP:
RDT_Msg("%s -- %s\n",
"po(ke address [word ...]",
"store words of memory" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoWPoke, 0 );
continue;
}
switch( RDT_CmdMatch("bpoke", 3) ) {
case MATCH_HELP:
RDT_Msg("%s -- %s\n",
"bpo(ke address [byte ...]",
"store bytes of memory" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoBPoke, 0 );
continue;
}
switch( RDT_CmdMatch("save", 1) ) {
case MATCH_HELP:
RDT_Msg( "%s -- %s\n",
"s(ave [threadid]",
"save module names for quick dbx start" );
break;
case MATCH_INVOKE:
RDT_DoWithConnection( RDT_DoSave, 0 );
continue;
}
switch( RDT_CmdMatch("quit", 4 ) ) {
case MATCH_HELP:
RDT_Msg("quit -- kill XR world\n");
break;
case MATCH_INVOKE:
if( !RDT_connected ) {
RDT_Msg("Good-bye.\n");
return;
}
if( RDT_DoKillWorld() != 0 ) {
RDT_Msg("Warning: debuggee not killed.\n");
}
return;
}
switch( RDT_CmdMatch("connect", 4 ) ) {
case MATCH_HELP:
RDT_Msg( "%s -- %s\n",
"connect [host [port]]", "establish connection" );
break;
case MATCH_INVOKE:
if( RDT_DoConnect() == 0 ) {
RDT_DoWithConnection( RDT_DoGetDebuggeeProtocolVersion,
RDT_PROCS_VERSION );
RDT_Msg("For dbx:\nignore 30 2 11 10\ncont\n\n");
}
continue;
}
switch( RDT_CmdMatch("disconnect", 4 ) ) {
case MATCH_HELP:
RDT_Msg( "%s -- %s\n",
"disconnect", "break connection" );
break;
case MATCH_INVOKE:
(void) RDT_DoDisconnect(TRUE);
continue;
}
switch( RDT_CmdMatch("?", 1 ) ) {
case MATCH_HELP:
RDT_Msg("? (command) -- print help message\n");
continue;
case MATCH_INVOKE:
continue;
}
{ /* bad command ... */
RDT_Msg("Bad command: %s\n", RDT_cmd);
}
}
}
main(argc, argv)
int argc;
char **argv;
{
bool initialConnectionRequested = FALSE;
if( argc > 3 ) {
goto Usage;
}
if( argc > 1 ) {
RDT_SetDebuggeeName(argv[1]);
if( argc > 2 ) {
int tPort = atoi(argv[2]);
if( tPort < 0 ) {
RDT_Msg("Bad port: %s\n", argv[2]);
goto Usage;
}
RDT_debuggeePort = ((unsigned)(tPort));
}
initialConnectionRequested = TRUE;
}
RDT_Main(initialConnectionRequested);
exit(0);
Usage:
RDT_Msg("Usage: %s [name [port]]\n", argv[0]);
exit(1);
}